home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / utils / sound / convrtr / amiga / amisox_w / 8svx.c next >
Encoding:
C/C++ Source or Header  |  1992-05-04  |  8.2 KB  |  333 lines

  1. /*
  2.  * Amiga 8SVX format handler: W V Neisius, February 1992
  3.  */
  4.  
  5. #include <math.h>
  6. #include "st.h"
  7.  
  8. extern errno;
  9. extern char *sys_errlist[];
  10.  
  11. /* Private data used by writer */
  12. struct svxpriv {
  13.         unsigned long nsamples;
  14.     FILE *ch[4];
  15. };
  16.  
  17. #ifndef SEEK_CUR
  18. #define SEEK_CUR        1
  19. #endif
  20. #ifndef SEEK_SET
  21. #define SEEK_SET        0
  22. #endif
  23.  
  24. /*======================================================================*/
  25. /*                         8SVXSTARTREAD                                */
  26. /*======================================================================*/
  27.  
  28. svxstartread(ft)
  29. ft_t ft;
  30. {
  31.     struct svxpriv *p = (struct svxpriv *) ft->priv;
  32.  
  33.     char buf[12];
  34.     char *endptr;
  35.     char *chunk_buf;
  36.  
  37.     unsigned long totalsize;
  38.     unsigned long chunksize;
  39.  
  40.     int channels;
  41.     int rate;
  42.     int littlendian = 0;
  43.     int i;
  44.  
  45.     unsigned long chan1_pos;
  46.  
  47.     rate = 0;
  48.     channels = 1;
  49.  
  50.     /* read FORM chunk */
  51.     if (fread(buf, 1, 4, ft->fp) != 4 || strncmp(buf, "FORM", 4) != 0)
  52.         fail("8SVX: header does not begin with magic word 'FORM'");
  53.     totalsize = rblong(ft);
  54.     if (fread(buf, 1, 4, ft->fp) != 4 || strncmp(buf, "8SVX", 4) != 0)
  55.         fail("8SVX: 'FORM' chunk does not specify '8SVX' as type");
  56.  
  57.     /* read chunks until 'BODY' (or end) */
  58.     while (fread(buf,1,4,ft->fp) == 4 && strncmp(buf,"BODY",4) != 0) {
  59.         if (strncmp(buf,"VHDR",4) == 0) {
  60.             chunksize = rblong(ft);
  61.             if (chunksize != 20)
  62.                 fail ("8SVX: VHDR chunk has bad size");
  63.             fseek(ft->fp,12,SEEK_CUR);
  64.             rate = rbshort(ft);
  65.             fseek(ft->fp,1,SEEK_CUR);
  66.             fread(buf,1,1,ft->fp);
  67.             if (buf[0] != 0)
  68.                 fail ("8SVX: unsupported data compression");
  69.             fseek(ft->fp,4,SEEK_CUR);
  70.             continue;
  71.         }
  72.  
  73.         if (strncmp(buf,"ANNO",4) == 0) {
  74.             chunksize = rblong(ft);
  75.             if (chunksize & 1)
  76.                 chunksize++;
  77.             chunk_buf = (char *) malloc(chunksize + 1);
  78.             for (i = 0; i < chunksize; i ++) {
  79.                 if (fread (&chunk_buf[i],1,1,ft->fp) != 1)
  80.                     fail("8SVX: Unexpected EOF in ANNO header");
  81.             }
  82.             chunk_buf[i] = '\0';
  83.             report ("%s",chunk_buf);
  84.             free(chunk_buf);
  85.  
  86.             continue;
  87.         }
  88.  
  89.         if (strncmp(buf,"NAME",4) == 0) {
  90.             chunksize = rblong(ft);
  91.             if (chunksize & 1)
  92.                 chunksize++;
  93.             chunk_buf = (char *) malloc(chunksize + 1);
  94.             for (i = 0; i < chunksize; i ++) {
  95.                 if (fread (&chunk_buf[i],1,1,ft->fp) != 1)
  96.                     fail("8SVX: Unexpected EOF in NAME header");
  97.             }
  98.             chunk_buf[i] = '\0';
  99.             report ("%s",chunk_buf);
  100.             free(chunk_buf);
  101.  
  102.             continue;
  103.         }
  104.  
  105.         if (strncmp(buf,"CHAN",4) == 0) {
  106.             chunksize = rblong(ft);
  107.             if (chunksize != 4) 
  108.                 fail("8SVX: Short channel chunk");
  109.             channels = rblong(ft);
  110.             channels = (channels & 0x01) + 
  111.                     ((channels & 0x02) >> 1) +
  112.                        ((channels & 0x04) >> 2) + 
  113.                     ((channels & 0x08) >> 3);
  114.  
  115.             continue;
  116.         }
  117.  
  118.         /* some other kind of chunk */
  119.         chunksize = rblong(ft);
  120.         if (chunksize & 1)
  121.             chunksize++;
  122.         fseek(ft->fp,chunksize,SEEK_CUR);
  123.         continue;
  124.  
  125.     }
  126.  
  127.     if (rate == 0)
  128.         fail ("8SVX: invalid rate");
  129.     if (strncmp(buf,"BODY",4) != 0)
  130.         fail ("8SVX: BODY chunk not found");
  131.     p->nsamples = rblong(ft);
  132.  
  133.     ft->info.channels = channels;
  134.     ft->info.rate = rate;
  135.     ft->info.style = SIGN2;
  136.     ft->info.size = BYTE;
  137.  
  138.     /* open files to channels */
  139.     p->ch[0] = ft->fp;
  140.     chan1_pos = ftell(p->ch[0]);
  141.  
  142.     for (i = 1; i < channels; i++) {
  143.         if ((p->ch[i] = fopen(ft->filename, READBINARY)) == NULL)
  144.             fail("Can't open channel file '%s': %s",
  145.                 ft->filename, sys_errlist[errno]);
  146.  
  147.         /* position channel files */
  148.         if (fseek(p->ch[i],chan1_pos,SEEK_SET))
  149.             fail ("Can't position channel %d: %s",i,sys_errlist[errno]);
  150.         if (fseek(p->ch[i],p->nsamples/channels*i,SEEK_CUR))
  151.             fail ("Can't seek channel %d: %s",i,sys_errlist[errno]);
  152.     }
  153.  
  154.  
  155.     endptr = (char *) &littlendian;
  156.     *endptr = 1;
  157.     if (littlendian == 1)
  158.         ft->swap = 1;
  159.  
  160. }
  161.  
  162. /*======================================================================*/
  163. /*                         8SVXREAD                                     */
  164. /*======================================================================*/
  165. svxread(ft, buf, nsamp) 
  166. ft_t ft;
  167. long *buf, nsamp;
  168. {
  169.     register unsigned long datum;
  170.     int done = 0;
  171.     int i;
  172.  
  173.     struct svxpriv *p = (struct svxpriv *) ft->priv;
  174.  
  175.     while (done < nsamp) {
  176.         for (i = 0; i < ft->info.channels; i++) {
  177.             datum = getc(p->ch[i]);
  178.             if (feof(p->ch[i]))
  179.                 return done;
  180.             /* scale signed up to long's range */
  181.             *buf++ = LEFT(datum, 24);
  182.         }
  183.         done += ft->info.channels;
  184.     }
  185.     return done;
  186. }
  187.  
  188. /*======================================================================*/
  189. /*                         8SVXSTOPREAD                                 */
  190. /*======================================================================*/
  191. svxstopread(ft)
  192. ft_t ft;
  193. {
  194.     int i;
  195.  
  196.     struct svxpriv *p = (struct svxpriv *) ft->priv;
  197.  
  198.     /* close channel files */
  199.     for (i = 1; i < ft->info.channels; i++) {
  200.         fclose (p->ch[i]);
  201.     }
  202. }
  203.  
  204. /*======================================================================*/
  205. /*                         8SVXSTARTWRITE                               */
  206. /*======================================================================*/
  207. svxstartwrite(ft)
  208. ft_t ft;
  209. {
  210.     struct svxpriv *p = (struct svxpriv *) ft->priv;
  211.     int littlendian = 0;
  212.     int i;
  213.     char *endptr;
  214.  
  215.     /* open channel output files */
  216.     p->ch[0] = ft->fp;
  217.     for (i = 1; i < ft->info.channels; i++) {
  218. #ifdef AMIGA
  219.         if ((p->ch[i] = (FILE *)tmpfile()) == NULL)
  220.             fail("Can't open channel output file: %s",
  221.                 sys_errlist[errno]);
  222. #else    /* probably didn't need to separate these, but don't *
  223.          * like to change code I don't need to... --dgc3     */
  224.         if ((p->ch[i] = tmpfile()) == NULL)
  225.             fail("Can't open channel output file: %s",
  226.                 sys_errlist[errno]);
  227. #endif
  228.     }
  229.  
  230.     /* write header (channel 0) */
  231.     ft->info.style = SIGN2;
  232.     ft->info.size = BYTE;
  233.  
  234.     p->nsamples = 0;
  235.     svxwriteheader(ft, p->nsamples);
  236.  
  237.     endptr = (char *) &littlendian;
  238.     *endptr = 1;
  239.     if (littlendian == 1)
  240.         ft->swap = 1;
  241. }
  242.  
  243. /*======================================================================*/
  244. /*                         8SVXWRITE                                    */
  245. /*======================================================================*/
  246.  
  247. svxwrite(ft, buf, len)
  248. ft_t ft;
  249. long *buf, len;
  250. {
  251.     struct svxpriv *p = (struct svxpriv *) ft->priv;
  252.  
  253.     register long datum;
  254.     int done = 0;
  255.     int i;
  256.  
  257.     p->nsamples += len;
  258.  
  259.     while(done < len) {
  260.         for (i = 0; i < ft->info.channels; i++) {
  261.             datum = RIGHT(*buf++, 24);
  262.             putc(datum, p->ch[i]);
  263.         }
  264.         done += ft->info.channels;
  265.     }
  266. }
  267.  
  268. /*======================================================================*/
  269. /*                         8SVXSTOPWRITE                                */
  270. /*======================================================================*/
  271.  
  272. svxstopwrite(ft)
  273. ft_t ft;
  274. {
  275.     struct svxpriv *p = (struct svxpriv *) ft->priv;
  276.  
  277.     int i;
  278.     int len;
  279.     char svxbuf[512];
  280.  
  281.     /* append all channel pieces to channel 0 */
  282.     /* close temp files */
  283.     for (i = 1; i < ft->info.channels; i++) {
  284.         if (fseek (p->ch[i], 0L, 0))
  285.             fail ("Can't rewind channel output file %d",i);
  286.         while (!feof(p->ch[i])) {
  287.             len = fread (svxbuf, 1, 512, p->ch[i]);
  288.             fwrite (svxbuf, 1, len, p->ch[0]);
  289.         }
  290.         fclose (p->ch[i]);
  291.     }
  292.  
  293.     /* fixup file sizes in header */
  294.     if (fseek(ft->fp, 0L, 0) != 0)
  295.         fail("can't rewind output file to rewrite 8SVX header");
  296.     svxwriteheader(ft, p->nsamples);
  297. }
  298.  
  299. /*======================================================================*/
  300. /*                         8SVXWRITEHEADER                              */
  301. /*======================================================================*/
  302. #define SVXHEADERSIZE 100
  303. svxwriteheader(ft,nsamples)
  304. ft_t ft;
  305. long nsamples;
  306. {
  307.     fputs ("FORM", ft->fp);
  308.     wblong(ft, nsamples + SVXHEADERSIZE - 8);  /* size of file */
  309.     fputs("8SVX", ft->fp); /* File type */
  310.  
  311.     fputs ("VHDR", ft->fp);
  312.     wblong(ft, (long) 20); /* number of bytes to follow */
  313.     wblong(ft, nsamples);  /* samples, 1-shot */
  314.     wblong(ft, (long) 0);  /* samples, repeat */
  315.     wblong(ft, (long) 0);  /* samples per repeat cycle */
  316.     wbshort(ft, ft->info.rate); /* samples per second */
  317.     fputc(1,ft->fp); /* number of octaves */
  318.     fputc(0,ft->fp); /* data compression (none) */
  319.     wbshort(ft,1); wbshort(ft,0); /* volume */
  320.  
  321.     fputs ("ANNO", ft->fp);
  322.     wblong(ft, (long) 32); /* length of block */
  323.     fputs ("File created by Sound Exchange  ", ft->fp);
  324.  
  325.     fputs ("CHAN", ft->fp);
  326.     wblong(ft, (long) 4);
  327.     wblong(ft, (ft->info.channels == 2) ? (long) 6 :
  328.            (ft->info.channels == 4) ? (long) 15 : (long) 2);
  329.  
  330.     fputs ("BODY", ft->fp);
  331.     wblong(ft, nsamples); /* samples in file */
  332. }
  333.